/// ------------------------------------------------------------------------------------------------------------------------------------
///
/// MIT License
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all
/// copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
/// SOFTWARE.
///
/// Copyright (c) 2022 ycz. All rights reserved.
///
/// Created by ycz on 2022/1/2.
///
/// @file  y_protocol.h
///
/// @brief
///     y_protocol 是一种用于嵌入式设备的简单通信协议，可以方便用于设备芯片间的通信。
///
/// ------------------------------------------------------------------------------------------------------------------------------------



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 防止当前头文件被重复引用
/// ------------------------------------------------------------------------------------------------------------------------------------

#ifndef _Y_PROTOCOL_H
#define _Y_PROTOCOL_H



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 头文件
/// ------------------------------------------------------------------------------------------------------------------------------------

#include <stdint.h>
#include <stdbool.h>



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 兼容 c++
/// ------------------------------------------------------------------------------------------------------------------------------------

#ifdef __cplusplus
extern "C" {
#endif



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 宏定义
/// ------------------------------------------------------------------------------------------------------------------------------------

#define Y_PROTOCOL_MAJOR 0  ///< 主版本     ( 主架构变化 )
#define Y_PROTOCOL_MINOR 1  ///< 次版本     ( 单个功能增加或修改 )
#define Y_PROTOCOL_PATCH 0  ///< 补丁版本    ( bug修复 )



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 枚举
/// ------------------------------------------------------------------------------------------------------------------------------------

/// 加密类型
typedef enum {
    ENCRYPT_NONE,      ///< 无加密
    ENCRYPT_CAESAR_3,  ///< 凯撒加密 (字符偏移3 A->D B->E 以此类推)
    ENCRYPT_XOR,       ///< 异或加密 (默认异或 0X4A)
    ENCRYPT_MIXED,     ///< 混和加密 (先凯撒，在异或)
} PROTOCOL_ENCRYPT_e;

/// 协议类型
typedef enum {
    PROTOCOL_O2O_V1 = 0X01,  ///< 一对一 协议类型 (适用于 软件模块间、芯片间、两个设备间、上位机间通信)
    PROTOCOL_M2M_V1 = 0X21,  ///< 多对多 协议类型（适用于 星型网络/网状网络 设备间通信）
} PROTOCOL_TYPE_e;

/// 消息模块枚举
typedef enum {
    MOD_LINK,      ///< 连接模块
    MOD_SYS,       ///< 系统模块
    MOD_FACTORY,   ///< 工厂测试模块
    MOD_OTA,       ///< 升级模块
    MOD_DEBUG,     ///< 调试模块
    MOD_INTER,     ///< 内部交互模块
    MOD_BUSINESS,  ///< 业务模块
    MOD_PROPERTY,  ///< 属性模块
    MOD_EVENT,     ///< 事件模块
    MOD_FUNCTION,  ///< 功能模块
} PROTOCOL_MOD_e;



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 结构体
/// ------------------------------------------------------------------------------------------------------------------------------------

#pragma pack(1)  // 设置结构体 1 字节对齐

/// 协议公共部分结构体
typedef struct {
    uint8_t  type;     ///< 协议类型
    uint8_t  encrypt;  ///< 加密类型
    uint8_t  num;      ///< 消息编号
    uint16_t size;     ///< 消息数据大小 （结构体中 除当前结构体以外的大小 不包含校验位）
} PROTOCOL_HEAD_st;

/// 一对一协议结构体
typedef struct {
    PROTOCOL_HEAD_st head;      ///< 协议头部分
    uint8_t          mod_id;    ///< 模块 id
    uint8_t          cmd_id;    ///< 命令 id
    uint16_t         cmd_size;  ///< 命令所带数据的大小
    uint8_t         *cmd_data;  ///< 命令所带数据
} PROTOCOL_O2O_V1_st;

/// 多对多协议结构体
typedef struct {
    PROTOCOL_HEAD_st head;         ///< 协议头部分
    uint8_t          send_mac[6];  ///< 发送端 mac
    uint8_t          recv_mac[6];  ///< 接收端 mac
    uint8_t          dev_type;     ///< 设备 类型
    uint16_t         dev_id;       ///< 设备 id
    uint8_t          wan_id;       ///< 网络 id
    uint8_t          mod_id;       ///< 模块 id
    uint8_t          cmd_id;       ///< 命令 id
    uint16_t         cmd_size;     ///< 命令所带数据的大小
    uint8_t         *cmd_data;     ///< 命令所带数据
} PROTOCOL_M2M_V1_st;

#pragma pack()  // 恢复结构体默认对其方式



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 函数 API
/// ------------------------------------------------------------------------------------------------------------------------------------

void               y_protocol_print_version();                                                 ///< 打印模块版本号
bool               y_protocol_pack(void *msg, uint8_t **pack_data, uint16_t *pack_size);       ///< 打包协议
bool               y_protocol_unpack(uint8_t *unpack_data, uint16_t unpack_size, void **msg);  ///< 解包协议
bool               y_protocol_delete(void *msg);                                               ///< 删除协议消息
char              *y_protocol_get_dev_str(uint8_t dev_type);                                   ///< 获取设备类型字符串
void              *y_protocol_dump(void *msg);                                                 ///< 转存消息 (y_ll_malloc 使用后需要释放)
void               y_protocol_print_m2m_msg(PROTOCOL_M2M_V1_st *msg);                          ///< 打印消息
PROTOCOL_M2M_V1_st y_protocol_create_m2m_msg(uint8_t  num,
                                             uint8_t *send_mac,
                                             uint8_t *recv_mac,
                                             uint8_t  dev_type,
                                             uint16_t dev_id,
                                             uint8_t  wan_id,
                                             uint8_t  mod_id,
                                             uint8_t  cmd_id,
                                             uint8_t *cmd_data,
                                             uint16_t cmd_size);  ///< 创建 m2m 消息



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 条件编译结尾
/// ------------------------------------------------------------------------------------------------------------------------------------

#ifdef __cplusplus
}
#endif  // __cplusplus 兼容 c++
#endif  // _Y_PROTOCOL_H 防止当前头文件被重复引用